module Pruning where

import Fitness

import Evaluator2
import Debug.Trace
import GameLoop

import Data.List
import qualified Data.Map as M
import qualified Data.Set as S

compareMoves x y = compare (snd x) (snd y)

appMove :: GameState -> App -> (App, GameState)
appMove state ap = (ap, swap_players $ snd $ apply ap state)

fitnessMove::(GameState->Int)->(App, GameState)->(App, Int)
fitnessMove cfitness (move, state) = (move, cfitness state)

getImportantSlots state = nubBy (\(n1, cs1) (n2, cs2)->(cs2 == cs1)) $ M.toList $ unPS $ state

isBestApp::Int->(App, Int)->Bool
isBestApp efitness a = (snd a) == efitness

futures::GameState->[(App, GameState)]
futures state = map (appMove state) moves
    where moves = concat [[LeftApp card (fst slot), RightApp (fst slot) card] | card <- cards, slot <- getImportantSlots $ proponent state]

-- Возвращает список ходов, имеющих лучшую оценку
bestApplications::GameState->[(App, Int)]
bestApplications state = [(app, negate $ fitness $ snd $ appMove state app) | app <- fst max']
    where
        max' = maximize 3 (negate 10000000) 10000000 state


maximize::Int->Int->Int->GameState->([App], Int)
maximize 0 a b s = ([], fitness s)
maximize d a b s = foldMaximize d a b (futures s) []
foldMaximize::Int->Int->Int->[(App, GameState)]->[App]->([App], Int)
foldMaximize d a b [] m = (m, a)
foldMaximize d a b (cm:rm) m
    | b <= a = (m, a)
    | a' > a = foldMaximize d a' b rm [fst cm]
    | a' == a = foldMaximize d a b rm ((fst cm) : m)
    | otherwise = foldMaximize d a b rm m
    where a' = negate $ snd $ maximize (d - 1) (negate b) (negate a) (snd cm)
